import {
  WebSocketGateway,
  WebSocketServer,
  SubscribeMessage,
  OnGatewayConnection,
  OnGatewayDisconnect,
  MessageBody,
  ConnectedSocket,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { AuthService } from '../auth/auth.service';
import { ChatService } from '../chat/chat.service';
import { ChatRoomService } from '../chatroom/chatroom.service';
import { PrismaService } from '../prisma/prisma.service';

@WebSocketGateway({
  cors: {
    origin: '*',
  },
})
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;

  private connectedUsers = new Map<
    string,
    { userId: number; username: string }
  >();

  constructor(
    private authService: AuthService,
    private chatService: ChatService,
    private chatRoomService: ChatRoomService,
    private prisma: PrismaService,
  ) {}

  async handleConnection(client: Socket) {
    try {
      const token =
        client.handshake.auth.token ||
        client.handshake.headers.authorization?.replace('Bearer ', '');

      if (!token) {
        client.disconnect();
        return;
      }

      const user = await this.authService.validateToken(token);

      if (!user) {
        client.disconnect();
        return;
      }

      // 存储用户信息
      this.connectedUsers.set(client.id, {
        userId: user.id,
        username: user.username,
      });

      // 更新用户在线状态
      await this.updateUserOnlineStatus(user.id, true);
    } catch (error) {
      client.disconnect();
    }
  }

  async handleDisconnect(client: Socket) {
    const userInfo = this.connectedUsers.get(client.id);
    if (userInfo) {
      // 更新用户离线状态
      await this.updateUserOnlineStatus(userInfo.userId, false);

      // 通知所有聊天室的用户该用户已离开
      // 获取用户所在的所有聊天室
      const userChatRooms = await this.prisma.chatRoomUser.findMany({
        where: { userId: userInfo.userId },
        select: { chatRoomId: true },
      });

      // 通知每个聊天室的用户
      for (const chatRoom of userChatRooms) {
        this.server.to(`chatroom_${chatRoom.chatRoomId}`).emit('userLeft', {
          userId: userInfo.userId,
          username: userInfo.username,
          chatRoomId: chatRoom.chatRoomId,
        });
      }

      this.connectedUsers.delete(client.id);
    }
  }

  @SubscribeMessage('joinChatRoom')
  async handleJoinChatRoom(
    @MessageBody() data: { chatRoomId: number },
    @ConnectedSocket() client: Socket,
  ) {
    const userInfo = this.connectedUsers.get(client.id);
    if (!userInfo) {
      return { error: '未认证' };
    }

    try {
      // 验证用户是否在聊天室中
      await this.chatRoomService.getChatRoomById(
        data.chatRoomId,
        userInfo.userId,
      );

      // 加入聊天室
      client.join(`chatroom_${data.chatRoomId}`);

      // 通知其他用户有新用户加入
      client.to(`chatroom_${data.chatRoomId}`).emit('userJoined', {
        userId: userInfo.userId,
        username: userInfo.username,
        chatRoomId: data.chatRoomId,
      });

      return { success: true };
    } catch (error) {
      return { error: error.message };
    }
  }

  @SubscribeMessage('leaveChatRoom')
  async handleLeaveChatRoom(
    @MessageBody() data: { chatRoomId: number },
    @ConnectedSocket() client: Socket,
  ) {
    const userInfo = this.connectedUsers.get(client.id);
    if (!userInfo) {
      return { error: '未认证' };
    }

    // 离开聊天室
    client.leave(`chatroom_${data.chatRoomId}`);

    // 通知其他用户有用户离开
    client.to(`chatroom_${data.chatRoomId}`).emit('userLeft', {
      userId: userInfo.userId,
      username: userInfo.username,
      chatRoomId: data.chatRoomId,
    });

    return { success: true };
  }

  @SubscribeMessage('sendMessage')
  async handleSendMessage(
    @MessageBody()
    data: {
      chatRoomId: number;
      content: string;
      type?: string;
      replyToId?: number;
      fileData?: any;
    },
    @ConnectedSocket() client: Socket,
  ) {
    const userInfo = this.connectedUsers.get(client.id);
    if (!userInfo) {
      return { error: '未认证' };
    }

    try {
      const message = await this.chatService.sendMessage(
        data.chatRoomId,
        userInfo.userId,
        {
          content: data.content,
          type: data.type || 'text',
          replyToId: data.replyToId,
          fileData: data.fileData,
        },
      );

      // 广播消息到聊天室（包括发送者）
      const roomName = `chatroom_${data.chatRoomId}`;
      const roomSockets = await this.server.in(roomName).fetchSockets();

      this.server.in(roomName).emit('newMessage', message);

      return { success: true, message };
    } catch (error) {
      return { error: error.message };
    }
  }

  @SubscribeMessage('typing')
  async handleTyping(
    @MessageBody() data: { chatRoomId: number; isTyping: boolean },
    @ConnectedSocket() client: Socket,
  ) {
    const userInfo = this.connectedUsers.get(client.id);
    if (!userInfo) {
      return;
    }

    // 广播打字状态
    client.to(`chatroom_${data.chatRoomId}`).emit('userTyping', {
      userId: userInfo.userId,
      username: userInfo.username,
      isTyping: data.isTyping,
      chatRoomId: data.chatRoomId,
    });
  }

  private async updateUserOnlineStatus(userId: number, isOnline: boolean) {
    try {
      await this.prisma.chatRoomUser.updateMany({
        where: { userId },
        data: {
          isOnline,
          lastSeen: new Date(),
        },
      });
    } catch (error) {
      console.error('❌ 更新用户在线状态失败:', error);
    }
  }
}
